import { formatNumber } from '../../editor/editor';
import { Cell, CellProps } from '../../doc/cell';

const ALLOW = [
	'0',
	'1',
	'2',
	'3',
	'4',
	'5',
	'6',
	'7',
	'8',
	'9',
	'.',
	'-',
	'Backspace',
	'Delete',
	'Tab',
	'ArrowLeft',
	'ArrowRight',
	'ArrowUp',
	'ArrowDown',
];

export function number(cell: Cell, attrs: CellProps) {
	function tidy(txt: string) {
		if (txt === '') {
			cell.setValue(undefined);
		} else {
			let num = parseFloat(txt);
			if (isNaN(num)) {
				cell.setValue(undefined);
			} else {
				let precision = attrs.precision ?? 0;
				if (precision < 0) precision = 0;
				if (num > Number.MAX_SAFE_INTEGER) {
					num = Number.MAX_SAFE_INTEGER;
				}
				num = Math.round(num * 10 ** precision) / 10 ** precision;
				cell.setValue(num);
			}
		}
	}

	if (!attrs.readonly) {
		cell.attr('contenteditable', 'plaintext-only');
	}
	cell.text(formatNumber(cell.getValue(), attrs.precision ?? 0));
	cell.on('blur', () => {
		const value = cell.getValue();
		if (value === undefined) {
			cell.text('');
			return;
		}
		const txt = formatNumber(value, attrs.precision ?? 0);
		cell.text(txt);
	});
	cell.on('keydown', (evt) => {
		if (evt.ctrlKey) {
			return;
		}
		if (!ALLOW.includes(evt.key)) {
			evt.preventDefault();
		}
		const selection = getSelection();
		if (!selection) {
			evt.preventDefault();
			return;
		}
		const range = selection.getRangeAt(0);
		if (!range) {
			evt.preventDefault();
			return;
		}
		if (evt.key === '-' && range.startOffset !== 0) {
			evt.preventDefault();
			return;
		}
		const precision = attrs.precision ?? 0;
		if ((precision < 1 || cell.text().includes('.')) && evt.key === '.') {
			evt.preventDefault();
		}
	});
	cell.on('input', () => {
		const txt = cell.text().trim();
		if (txt === '-' || txt === '.') {
			cell.setValue(0);
		} else {
			tidy(txt);
		}
		cell.emitChange();
	});
}
